FilterLevel *children;
gint offset;
gint ref_count;
+ gint ext_ref_count;
gint zero_ref_count;
gboolean visible;
};
{
GArray *array;
gint ref_count;
+ gint ext_ref_count;
gint visible_nodes;
gint parent_elt_index;
static void gtk_tree_model_filter_clear_cache_helper (GtkTreeModelFilter *filter,
FilterLevel *level);
+static void gtk_tree_model_filter_real_ref_node (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gboolean external);
static void gtk_tree_model_filter_real_unref_node (GtkTreeModel *model,
GtkTreeIter *iter,
+ gboolean external,
gboolean propagate_unref);
static void gtk_tree_model_filter_set_model (GtkTreeModelFilter *filter,
sizeof (FilterElt),
length);
new_level->ref_count = 0;
+ new_level->ext_ref_count = 0;
new_level->visible_nodes = 0;
new_level->parent_elt_index = parent_elt_index;
new_level->parent_level = parent_level;
filter_elt.offset = i;
filter_elt.zero_ref_count = 0;
filter_elt.ref_count = 0;
+ filter_elt.ext_ref_count = 0;
filter_elt.children = NULL;
filter_elt.visible = TRUE;
f_iter.user_data2 = &(g_array_index (new_level->array, FilterElt, new_level->array->len - 1));
if (new_level->parent_level || filter->priv->virtual_root)
- gtk_tree_model_filter_ref_node (GTK_TREE_MODEL (filter), &f_iter);
+ gtk_tree_model_filter_real_ref_node (GTK_TREE_MODEL (filter),
+ &f_iter, FALSE);
if (emit_inserted)
{
filter_elt.offset = 0;
filter_elt.zero_ref_count = 0;
filter_elt.ref_count = 0;
+ filter_elt.ext_ref_count = 0;
filter_elt.children = NULL;
filter_elt.visible = FALSE;
f_iter.user_data = new_level;
f_iter.user_data2 = &(g_array_index (new_level->array, FilterElt, new_level->array->len - 1));
- gtk_tree_model_filter_ref_node (GTK_TREE_MODEL (filter), &f_iter);
+ gtk_tree_model_filter_real_ref_node (GTK_TREE_MODEL (filter), &f_iter,
+ FALSE);
}
else if (new_level->array->len == 0)
gtk_tree_model_filter_free_level (filter, new_level, TRUE);
f_iter.user_data = filter_level;
f_iter.user_data2 = &(g_array_index (filter_level->array, FilterElt, i));
- gtk_tree_model_filter_unref_node (GTK_TREE_MODEL (filter), &f_iter);
+ gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
+ &f_iter, FALSE, TRUE);
}
}
- if (filter_level->ref_count == 0)
+ if (filter_level->ext_ref_count == 0)
{
FilterLevel *parent_level = filter_level->parent_level;
gint parent_elt_index = filter_level->parent_elt_index;
gtk_tree_model_filter_clear_cache_helper (filter, g_array_index (level->array, FilterElt, i).children);
}
- if (level->ref_count == 0 && level != filter->priv->root)
+ if (level->ext_ref_count == 0 && level != filter->priv->root &&
+ level->parent_level->ext_ref_count == 0)
{
gtk_tree_model_filter_free_level (filter, level, TRUE);
return;
elt.offset = offset;
elt.zero_ref_count = 0;
elt.ref_count = 0;
+ elt.ext_ref_count = 0;
elt.children = NULL;
/* visibility should be FALSE as we don't emit row_inserted */
elt.visible = FALSE;
f_iter.user_data = level;
f_iter.user_data2 = &g_array_index (level->array, FilterElt, *index);
- gtk_tree_model_filter_ref_node (GTK_TREE_MODEL (filter), &f_iter);
+ gtk_tree_model_filter_real_ref_node (GTK_TREE_MODEL (filter), &f_iter,
+ FALSE);
}
return &g_array_index (level->array, FilterElt, *index);
/* we distinguish a couple of cases:
* - root level, length > 1: emit row-deleted and remove.
* - root level, length == 1: emit row-deleted and keep in cache.
- * - level, length == 1: parent->ref_count > 1: emit row-deleted and keep.
+ * - level, length == 1: parent->ext_ref_count > 0: emit row-deleted
+ * and keep.
* - level, length > 1: emit row-deleted and remove.
* - else, remove level.
*
if (elt->children)
gtk_tree_model_filter_free_level (filter, elt->children, TRUE);
+ while (elt->ext_ref_count > 0)
+ gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
+ &iter, TRUE, FALSE);
while (elt->ref_count > 1)
gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
- &iter, FALSE);
+ &iter, FALSE, FALSE);
/* We must account for the filter model's reference, because the
* node is still present in the child model.
*/
if (parent_level || filter->priv->virtual_root)
- gtk_tree_model_filter_unref_node (GTK_TREE_MODEL (filter), &iter);
+ gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter), &iter,
+ FALSE, TRUE);
else if (elt->ref_count > 0)
gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
- &iter, FALSE);
+ &iter, FALSE, FALSE);
/* remove the node */
tmp = bsearch_elt_with_offset (level->array, elt->offset, &i);
}
gtk_tree_model_filter_increment_stamp (filter);
- gtk_tree_model_row_deleted (GTK_TREE_MODEL (filter), path);
+
+ /* Only if the node is in the root level (parent == NULL) or
+ * the parent is visible, a row-deleted signal is necessary.
+ */
+ if (!parent || parent->ext_ref_count > 0)
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (filter), path);
}
- else if ((length == 1 && parent && parent->ref_count > 1)
+ else if ((length == 1 && parent && parent->ext_ref_count > 0)
|| (length == 1 && level == filter->priv->root))
{
/* We emit row-deleted, but keep the node in the cache and
* in gtk_tree_model_filter_free_level), because the node is
* still present in the child model.
*/
+ while (elt->ext_ref_count > 0)
+ gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
+ &iter, TRUE, FALSE);
while (elt->ref_count > 1)
gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
- &iter, FALSE);
+ &iter, FALSE, FALSE);
/* Blow level away, including any child levels */
gtk_tree_model_filter_free_level (filter, level, TRUE);
signals_emitted = TRUE;
}
+ gtk_tree_model_filter_increment_stamp (filter);
+
/* We need to disallow to build new levels, because we are then pulling
* in a child in an invisible level. We only want to find path if it
* is in a visible level (and thus has a parent that is visible).
/* parent is probably being filtered out */
return;
- gtk_tree_model_filter_increment_stamp (filter);
-
gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (filter), &iter, path);
level = FILTER_LEVEL (iter.user_data);
* model's references on the node in case of level->parent or use
* of a virtual root are automatically destroyed by the child model.
*/
+ while (elt->ext_ref_count > 0)
+ gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter,
+ TRUE, FALSE);
while (elt->ref_count > 0)
- gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter, FALSE);
+ gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter,
+ FALSE, FALSE);
if (level->array->len == 1)
{
static void
gtk_tree_model_filter_ref_node (GtkTreeModel *model,
GtkTreeIter *iter)
+{
+ gtk_tree_model_filter_real_ref_node (model, iter, TRUE);
+}
+
+static void
+gtk_tree_model_filter_real_ref_node (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gboolean external)
{
GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
GtkTreeIter child_iter;
elt->ref_count++;
level->ref_count++;
- if (level->ref_count == 1)
+
+ if (external)
{
- FilterLevel *parent_level = level->parent_level;
- gint parent_elt_index = level->parent_elt_index;
+ elt->ext_ref_count++;
+ level->ext_ref_count++;
- /* we were at zero -- time to decrease the zero_ref_count val */
- while (parent_level)
+ if (level->ext_ref_count == 1)
{
- g_array_index (parent_level->array, FilterElt, parent_elt_index).zero_ref_count--;
+ FilterLevel *parent_level = level->parent_level;
+ gint parent_elt_index = level->parent_elt_index;
- parent_elt_index = parent_level->parent_elt_index;
- parent_level = parent_level->parent_level;
- }
+ /* we were at zero -- time to decrease the zero_ref_count val */
+ while (parent_level)
+ {
+ g_array_index (parent_level->array, FilterElt, parent_elt_index).zero_ref_count--;
+
+ parent_elt_index = parent_level->parent_elt_index;
+ parent_level = parent_level->parent_level;
+ }
- if (filter->priv->root != level)
- filter->priv->zero_ref_count--;
+ if (filter->priv->root != level)
+ filter->priv->zero_ref_count--;
+ }
}
}
gtk_tree_model_filter_unref_node (GtkTreeModel *model,
GtkTreeIter *iter)
{
- gtk_tree_model_filter_real_unref_node (model, iter, TRUE);
+ gtk_tree_model_filter_real_unref_node (model, iter, TRUE, TRUE);
}
static void
gtk_tree_model_filter_real_unref_node (GtkTreeModel *model,
GtkTreeIter *iter,
+ gboolean external,
gboolean propagate_unref)
{
GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
elt->ref_count--;
level->ref_count--;
- if (level->ref_count == 0)
+
+ if (external)
{
- FilterLevel *parent_level = level->parent_level;
- gint parent_elt_index = level->parent_elt_index;
+ elt->ext_ref_count--;
+ level->ext_ref_count--;
- /* we are at zero -- time to increase the zero_ref_count val */
- while (parent_level)
+ if (level->ext_ref_count == 0)
{
- g_array_index (parent_level->array, FilterElt, parent_elt_index).zero_ref_count++;
+ FilterLevel *parent_level = level->parent_level;
+ gint parent_elt_index = level->parent_elt_index;
- parent_elt_index = parent_level->parent_elt_index;
- parent_level = parent_level->parent_level;
- }
+ /* we are at zero -- time to increase the zero_ref_count val */
+ while (parent_level)
+ {
+ g_array_index (parent_level->array, FilterElt, parent_elt_index).zero_ref_count++;
+
+ parent_elt_index = parent_level->parent_elt_index;
+ parent_level = parent_level->parent_level;
+ }
- if (filter->priv->root != level)
- filter->priv->zero_ref_count++;
+ if (filter->priv->root != level)
+ filter->priv->zero_ref_count++;
+ }
}
}